package com.wu.shiro;

import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthenticatingRealm;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

import java.util.HashSet;
import java.util.Set;

/**
 * @author wuyanshen
 * @date 2019-01-13 11:57 AM
 * @discription AuthenticatingRealm 只有认证方法
 * AuthorizingRealm 有认证和授权方法
 */
public class MySecondeRealm extends AuthorizingRealm {

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        System.out.println("第二个Realm token是:"+authenticationToken);
        System.out.println(" doGetAuthenticationInfo token hash->"+authenticationToken.hashCode());

        //1.将AuthenticationToken转化成UserNamePasswordToken
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken;

        //2.UserNamePasswordToken中获取loginName
        String loginName = usernamePasswordToken.getUsername();

        //3.调用数据库获取loginName对应的记录
        System.out.println("从数据库获取到的user");

        //4.若记录不存在,则抛出AuthenticationException
        if ("unknown".equals(loginName)) {
            throw new UnknownAccountException("用户不存在");
        }

        if ("lala".equals(loginName)) {
            throw new LockedAccountException("用户被锁定");
        }
        //5.根据用户的情况,来构建AuthenticationInfo 对象返回
        //第一个参数principal:认证的实体信息,可以是userName,也可以是用户的实体对象
        //第二个参数credentials:密码
        String credentials = null;
        if ("admin".equals(loginName)) {
             credentials = "49d9fbf007fd95343492e607aa34455eeb062b26";
        }

        if ("user".equals(loginName)) {
            credentials = "16962ca194c20f8a1616c521318c37de8efeb537";
        }

//        String credentials = "123";
        //1):将密码md5加密
        //2):替换默认的密码比对器CredentialsMatcher为其他密码匹配器,如HashedCredentialsMatcher
        //3):加入盐,盐值需要唯一,使每个密码对应的md5值都不一样
        ByteSource salt = ByteSource.Util.bytes(loginName);

        //第三个参数realmName:当前realm对象的name,调用父类的getName()方法即可

        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(loginName,credentials,salt,getName());

        return info;
    }


    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("第二个Realm 准备授权...");
        //1.从PrincipalCollection中获取登录信息
        Object principal = principalCollection.getPrimaryPrincipal();

        //2.利用登录信息获取用户的角色或者权限信息
        Set<String> roles = new HashSet<>();
        roles.add("USER");
        if ("admin".equals(principal)) {
            roles.add("ADMIN");
        }

        //3.创建 SimpleAuthorizationInfo ,并设置Roles属性
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);

        //4.返回SimpleAuthorizationInfo
        return info;
    }

    public static void main(String[] args) {
        String algorithmName = "SHA1";
        Object credit = "123";
        ByteSource salt = ByteSource.Util.bytes("admin");
        int hashIterations = 1024;
        Object result = new SimpleHash(algorithmName, credit, salt, hashIterations);
        System.out.println(result);
    }
}
